package org.anyin.gitee.cloud.lib.core.config;

import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.anyin.gitee.cloud.lib.core.enums.CommonExCodeEnum;
import org.anyin.gitee.cloud.lib.core.exceptions.CommonException;
import org.anyin.gitee.cloud.lib.core.utils.RequestIdUtil;
import org.anyin.gitee.cloud.lib.core.web.ApiResponse;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.UUID;

@Slf4j
public abstract class DefaultApiHandler {

    public abstract Object invokeAPI(ProceedingJoinPoint pjp) throws Throwable;

    protected Object handle(ProceedingJoinPoint pjp) throws Throwable {
        MethodSignature ms = (MethodSignature) pjp.getSignature();
        String apiClassName = pjp.getTarget().getClass().getSimpleName();
        String methodName = ms.getName();
        String apiName = apiClassName.concat(":").concat(methodName);

        Class<?> returnClazz = ms.getReturnType();
        Object returnValue = null;
        StringBuffer reqParam = new StringBuffer("");
        try {
            Object[] args = pjp.getArgs();
            if (log.isInfoEnabled()) {
                if(args != null && args.length > 0){
                    for(Object o : args){
                        if(!(o instanceof HttpServletRequest) && !(o instanceof HttpServletResponse) && !(o instanceof CommonsMultipartFile)) {
                            reqParam.append(JSONUtil.toJsonStr(o)).append(",");
                            log.info("@@{} started, request: {}", apiName, JSONUtil.toJsonStr(o));
                        }
                    }

                }
            }
            returnValue = pjp.proceed();
            this.handleSuccess(returnValue);
        } catch (CommonException e) {
            returnValue = this.handleBusinessError(e, apiName, returnClazz);
        } catch (Throwable e) {
            throw e;
        }

        if (log.isInfoEnabled()) {
            log.info("@@{} done, response: {}", apiName,  JSONUtil.toJsonStr(returnValue));
        }
        return returnValue;
    }

    /**
     * 业务异常
     */
    private Object handleBusinessError(CommonException e, String apiName, Class<?> returnClazz) {
        log.error("@Meet error when do " + apiName + "[" + e.getErrorCode() + "]:" + e.getErrorMessage(), e);
        Object returnValue = null;
        try {
            returnValue = returnClazz.newInstance();
            if (returnValue instanceof ApiResponse) {
                ApiResponse response = (ApiResponse) returnValue;
                response.setId(RequestIdUtil.getRequestId().toString());
                response.setCode(e.getErrorCode());
                response.setMessage(e.getErrorMessage());
            }
        } catch (Exception e1) {
            throw new RuntimeException(e1);
        }
        return returnValue;
    }

    /**
     * 处理成功
     */
    private void handleSuccess(Object returnValue) {
        if (returnValue instanceof ApiResponse) {
            ApiResponse response = (ApiResponse) returnValue;
            if(StringUtils.isEmpty(response.getCode())){
                response.setCode(CommonExCodeEnum.SUCCESS.getCode());
                response.setMessage(CommonExCodeEnum.SUCCESS.getMessage());
            }
            response.setId(RequestIdUtil.getRequestId().toString());
        }
    }
}
